package com.vf.cloud.rendering.server.signalling.server;

import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import com.vf.cloud.rendering.common.constant.Cache;
import com.vf.cloud.rendering.common.factory.UEFactory;
import com.vf.cloud.rendering.server.signalling.SignallingServer;
import com.vf.cloud.rendering.server.signalling.channel.SignallingChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Server implements Runnable {

	private EventLoopGroup boss;
	private EventLoopGroup work;
	private ExecutorService executor;
	private Channel channel;

	/**
	 * 0-停止 1-正在启动 2-运行中 3-停止中
	 */
	private int status = 0;

	public void run() {
		executor = Executors.newFixedThreadPool(1);
		try {
			executor.submit(new Callable<String>() {
				@Override
				public String call() throws Exception {
					start();
					return "";
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void start() {
		try {

			status = 1;
			ServerBootstrap bootstrap = new ServerBootstrap();
			boss = new NioEventLoopGroup();
			work = new NioEventLoopGroup();

			log.info(">>>正在启动 --> SignallingServer:" + Cache.signalling.getInnerPort());
			bootstrap.group(boss, work);
			bootstrap.channel(NioServerSocketChannel.class);
			bootstrap.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(512 * 1024, 1024 * 1024));
			bootstrap.childHandler(new SignallingChannelInitializer());
			channel = bootstrap.bind(Cache.signalling.getInnerPort()).sync().channel();
			log.info(">>>启动成功 --> SignallingServer:" + Cache.signalling.getInnerPort());
			status = 2;
			channel.closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
			status = 3;
			log.error(">>>启动异常 --> SignallingServer:", e);
		} finally {
			work.shutdownGracefully();
			boss.shutdownGracefully();
			if (executor != null)
				executor.shutdownNow();
			log.info(">>>已关闭 --> SignallingServer:" + Cache.signalling.getInnerPort());
			status = 0;
		}
	}

	public void stop() {
		status = 3;
		UEFactory.getInstance().KillAllUeClient();
		if (channel != null) {
			channel.close();
			channel = null;
		} else {
			status = 0;
		}
	}

	public void restart() {
		stop();
	}

	public int getStatus() {
		return status;
	}

	public void destroy() {
		if (reconnectScheduledExecutor != null) {
			reconnectScheduledExecutor.shutdown();
		}
		stop();
	}

	private ScheduledExecutorService reconnectScheduledExecutor;

	public void reconnect() {
		reconnectScheduledExecutor = new ScheduledThreadPoolExecutor(1);
		reconnectScheduledExecutor.scheduleWithFixedDelay(new TimerTask() {
			@Override
			public void run() {
				if (Cache.signalling != null && SignallingServer.getInstance().verify(Cache.signalling)) {
					if (status == 0) {
						SignallingServer.getInstance().run();
					} else if (status == 2) {
					} else {
						log.info(">>>重连中 --> SignallingServer:" + status);
					}
				}
			}
		}, 0, 5, TimeUnit.SECONDS);
	}

}
